package com.koron.operation.classes.shift.task;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.koron.bean.base.BaseBean;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.task.web.entity.CronTask;
import com.koron.common.task.web.service.XxlJobService;
import com.koron.operation.classes.schedule.bean.dto.ClassesShiftDTO;
import com.koron.operation.classes.schedule.bean.dto.ScheduleDTO;
import com.koron.operation.classes.schedule.bean.po.ClassesSchedule;
import com.koron.operation.classes.schedule.bean.po.ClassesShift;
import com.koron.operation.classes.schedule.bean.po.ClassesStaff;
import com.koron.operation.classes.schedule.service.ClassesScheduleService;
import com.koron.operation.classes.schedule.service.ClassesShiftService;
import com.koron.operation.classes.shift.bean.dto.ChangeShiftDTO;
import com.koron.operation.classes.shift.bean.dto.ShiftRecordDTO;
import com.koron.operation.classes.shift.bean.po.ClassesDutyRecord;
import com.koron.operation.classes.shift.bean.po.ClassesShiftRecord;
import com.koron.operation.classes.shift.bean.po.ClassesTip;
import com.koron.operation.classes.shift.bean.query.ShiftQuery;
import com.koron.operation.classes.shift.bean.query.ShiftRecordQuery;
import com.koron.operation.classes.shift.service.ClassesDutyRecordService;
import com.koron.operation.classes.shift.service.ClassesTipService;
import com.koron.operation.classes.shift.service.ShiftService;
import com.koron.operation.classes.shift.service.impl.ClassesShiftRecordServiceImpl;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.koron.ebs.mybatis.ADOConnection;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 自动交接班
 * <p>
 * 规则：
 * 保存排班方案时：
 * 值班结束时间 < 当前时间                   的班次都变成2已交班
 * 值班开始时间 < 当前时间 < 值班结束时间      的班次变成2已交班，并且创建交接班计划
 * 当前时间 < 值班开始时间                   的班次不变
 * <p>
 * 如果 值班开始时间 都是在 当前时间 之后的，首班创建交接班计划
 * <p>
 * 执行交接班任务时，需要给下一班创建交接班计划，并删除当前计划
 * <p>
 * 删除排班方案时，删除所有计划
 * <p>
 * 以下的bizId、businessId都是指scheduleId，也就是排班方案的id
 *
 * @author jzp
 * @since 2021/12/30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ShiftTask {
    private final ShiftService shiftService;
    private final ClassesShiftService classesShiftService;
    private final ClassesScheduleService classesScheduleService;
    private final ClassesShiftRecordServiceImpl classesShiftRecordService;
    private final XxlJobService xxlJobService;
    private final ClassesTipService classesTipService;
    private final ClassesDutyRecordService classesDutyRecordService;

    private String getCurrDs() {
        return ThreadLocalContext.get().getCurrDs();
    }

    private void setCurrDs(String mark) {
        ThreadLocalContext.get().setCurrDs(mark);
    }

    public void createTask(String scheduleId, String mark) {
        ScheduleDTO scheduleDTO = ADOConnection.runTask(mark, classesScheduleService, "getDtoById", ScheduleDTO.class, scheduleId);
        createTask(scheduleDTO, mark);
    }

    /**
     * 创建交接班任务
     */
    public void createTask(ScheduleDTO scheduleDTO, String mark) {
        // 如果不需要创建任务，则直接返回
        if (!checkBeforeCreate(scheduleDTO)) {
            return;
        }
        List<List<ClassesShiftDTO>> shiftListSource = scheduleDTO.getShiftList();
        List<ClassesShiftDTO> shiftList = new ArrayList<>();
        shiftListSource.forEach(shiftList::addAll);
        Date currentDate = new Date();
        // 尝试交接班，并获取当前正在值班的班次
        ClassesShiftDTO currShift = attemptShift(shiftList, mark, scheduleDTO);
        ShiftTask shiftTask = SpringUtil.getBean(ShiftTask.class);
        if (currShift != null) {
            // 创建交班计划
            shiftTask.createHandoverTask(scheduleDTO.getId(), currShift.getEndTime(), currShift.getUpdateByName(), scheduleDTO.getName(), mark);
        } else {
            // 如果最后一班的结束时间已过，就不用创建计划
            if (scheduleDTO.getEndTime().before(currentDate)) {
                return;
            }
            // 获取最近的未接班的班次,创建接班计划
            shiftList.stream()
                    .filter(e -> new Integer(0).equals(e.getStatus()))
                    .findFirst()
                    .ifPresent(classesShiftDTO -> shiftTask.createTakeoverTask(scheduleDTO.getId(), classesShiftDTO.getStartTime(), classesShiftDTO.getUpdateByName(), scheduleDTO.getName(), mark));
        }
        log.info("启动定时任务，排班方案：{}", scheduleDTO.getName());
    }

    /**
     * 删除交接班任务
     */
    @SneakyThrows
    @Async
    public void deleteTask(String id) {
        // 要等任务执行完毕才能删除
        Thread.sleep(10000);
        xxlJobService.remove(id);
    }

    @SneakyThrows
    @Async
    public void deleteTopicTask(String id) {
        // 删除通知i任务
        xxlJobService.remove("T"+id);
        xxlJobService.remove("H"+id);
    }

    @SneakyThrows
    @Async
    public void startTopicTask(String id) {
        // 删除通知i任务
        xxlJobService.start("T"+id);
        xxlJobService.start("H"+id);
    }

    /**
     * 创建前检查
     * false则不通过不通过检查，不会执行后续代码
     */
    private boolean checkBeforeCreate(ScheduleDTO scheduleDTO) {
        Integer autoSwitch = scheduleDTO.getAutoSwitch();
        if (autoSwitch == null) {
            return false;
        }
        if (1 == scheduleDTO.getStatus()) {
            // 如果停用了，也不通过检查
            return false;
        }
        // 如果需要创建任务
        if (autoSwitch > 0) {
            return true;
        }
        ShiftTask shiftTask = SpringUtil.getBean(ShiftTask.class);
        shiftTask.deleteTask(scheduleDTO.getId());
        return false;
    }

    /**
     * 创建交班计划
     */
    @SneakyThrows
    @Async
    public void createHandoverTask(String bizId, Date date, String username, String scheduleName, String mark) {
        CronTask cronTask = xxlJobService.getCronTaskById(bizId);
        String cronStr = genCronStr(date);
        if (mark != null) {
            setCurrDs(mark);
        }
        String jobName = null;
        if (scheduleName != null) {
            jobName = scheduleName + "[" + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm") + "]";
        }
        String jobBean = "executeHandoverTask";
        if (cronTask != null) {
            // 更新任务，要先等任务停止
            Thread.sleep(5000);
            log.info("更新：{}", jobName);
            xxlJobService.update(bizId, cronStr, cronTask.getMark(), jobName, username, jobBean);
            xxlJobService.start(bizId);
            log.info("当前状态为：{}", cronTask.getStatus());
        } else {
            log.info("创建：{}", jobName);
            ClassesSchedule classesSchedule = ADOConnection.runTask(mark, classesScheduleService, "getById", ClassesSchedule.class, bizId);
            // 创建时要确保是自动交接班且启用, 如果需要创建任务
            if (classesSchedule.getAutoSwitch() > 0 && classesSchedule.getStatus() == 0) {
                xxlJobService.addSimpleJob(bizId, cronStr, mark, jobName, username, jobBean, 10);
                xxlJobService.start(bizId);
            }
        }
    }

    /**
     * 创建接班计划
     */
    @SneakyThrows
    @Async
    public void createTakeoverTask(String bizId, Date date, String username, String scheduleName, String mark) {
        CronTask cronTask = xxlJobService.getCronTaskById(bizId);
        String cronStr = genCronStr(date);
        if (mark != null) {
            setCurrDs(mark);
        }
        String jobName = null;
        if (scheduleName != null) {
            jobName = scheduleName + "[" + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm") + "]";
        }
        String jobBean = "executeTakeoverTask";
        if (cronTask != null) {
            // 更新任务
            Thread.sleep(5000);
            log.info("更新：{}", jobName);
            xxlJobService.update(bizId, cronStr, cronTask.getMark(), jobName, username, jobBean);
            xxlJobService.start(bizId);
        } else {
            log.info("创建：{}", jobName);
            ClassesSchedule classesSchedule = ADOConnection.runTask(mark, classesScheduleService, "getById", ClassesSchedule.class, bizId);
            // 创建时要确保是自动交接班且启用, 如果需要创建任务
            if (classesSchedule.getAutoSwitch() > 0 && classesSchedule.getStatus() == 0) {
                xxlJobService.addSimpleJob(bizId, cronStr, mark, jobName, username, jobBean, 10);
                xxlJobService.start(bizId);
            }
        }
    }

    private String genCronStr(Date date) {
        //秒 分钟 小时 日 月 星期 年
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return "0 " +
                cal.get(Calendar.MINUTE) + " " +
                cal.get(Calendar.HOUR_OF_DAY) + " " +
                cal.get(Calendar.DAY_OF_MONTH) + " " +
                (cal.get(Calendar.MONTH) + 1) + " " +
                "? " +
                cal.get(Calendar.YEAR);
    }

    /**
     * 尝试交接班
     * 前面过期的班次都不会保存配置和工作完成情况
     * 值班结束时间 < 当前时间                   强制交接班 班次都变成2已交班
     * 值班开始时间 < 当前时间 < 值班结束时间      的班次变成2已交班，并且创建交接班计划
     */
    private ClassesShiftDTO attemptShift(List<ClassesShiftDTO> shiftList, String mark, ScheduleDTO scheduleDTO) {
        log.info("尝试交接班");
        Date currentDate = new Date();
        // 值班结束时间 < 当前时间的数据 全部都自动交接班
        List<ClassesShiftDTO> shiftList0 = shiftList.stream().filter(e -> e.getEndTime().before(currentDate)).collect(Collectors.toList());

        // 需要修改状态的班次id集合
        List<String> stateShiftIds = new ArrayList<>();
        // 需要新增交接班记录的集合
        List<ClassesShiftRecord> classesShiftRecords = new ArrayList<>();
        // 交接班事项集合
        List<ClassesTip> tips = null;
        if (!CollectionUtils.isEmpty(shiftList0)) {
            // 如果未接班，需要先接班
            // 查询当前交接班记录
            ShiftRecordDTO currShiftRecordDTO = getCurrShiftRecordDTO(scheduleDTO.getId(), getCurrDs());
            tips = currShiftRecordDTO.getTips();
            // 如果本值是已交班且下值是未接班
            Optional.ofNullable(currShiftRecordDTO)
                    .map(ShiftRecordDTO::getThisShift)
                    .map(ClassesShift::getStatus)
                    .ifPresent(e -> {
                        ClassesShiftDTO nextShift = currShiftRecordDTO.getNextShift();
                        if (e == 2 && nextShift != null && nextShift.getStatus() == 0) {
                            // 当前班别方案和下值班别方案必须是同一个方案
                            Assert.isTrue(Objects.equals(nextShift.getScheduleId(), scheduleDTO.getId()), "请确保【" + currShiftRecordDTO.getScheduleName() + "】和当前排班方案能正常衔接");
                            // 执行接班，普通接班
                            ADOConnection.runTask(mark, shiftService, "takeover", Boolean.class, currShiftRecordDTO.getId());
                            logShift(nextShift.getStartTime(), nextShift.getEndTime(), nextShift.getName(), "执行接班");
                        } else if (e == 1 && !Objects.equals(currShiftRecordDTO.getScheduleId(), scheduleDTO.getId()) && nextShift != null && nextShift.getStatus() == 0) {
                            // 如果不是当前排班方案，且本值状态为1
                            // 本值交班
                            ADOConnection.runTask(mark, shiftService, "handover", Boolean.class, currShiftRecordDTO);
                            ClassesShiftDTO thisShift = currShiftRecordDTO.getThisShift();
                            logShift(thisShift.getStartTime(), thisShift.getEndTime(), thisShift.getName(), "执行交班");
                            // 下值接班
                            ADOConnection.runTask(mark, shiftService, "takeover", Boolean.class, currShiftRecordDTO.getId());
                            logShift(nextShift.getStartTime(), nextShift.getEndTime(), nextShift.getName(), "执行接班");
                        }
                    });
        }
        // 值班记录集合
        List<ClassesDutyRecord> dutyRecords = new ArrayList<>();

        for (int i = 0; i < shiftList0.size(); i++) {
            ClassesShiftDTO classesShiftDTO = shiftList0.get(i);
            // 已交班的直接跳过
            if (new Integer(2).equals(classesShiftDTO.getStatus())) {
                continue;
            }

            // 0和1的 交班且生成交接班记录
            //   交班
            stateShiftIds.add(classesShiftDTO.getId());
            //   生成交接班记录
            ClassesShiftRecord shiftRecord = new ClassesShiftRecord();
            shiftRecord.setScheduleId(classesShiftDTO.getScheduleId());
            shiftRecord.setThisShiftId(classesShiftDTO.getId());
            shiftRecord.setThisTime(classesShiftDTO.getEndTime());
            shiftRecord.setNextTime(classesShiftDTO.getEndTime());
            if (i + 1 == shiftList0.size()) {
                shiftRecord.setStatus(0);
                // 如果有下一班次
                if (shiftList.size() > i + 1) {
                    shiftRecord.setNextShiftId(shiftList.get(i + 1).getId());
                } else {
                    // 如果没有下一班次，不添加交接班记录，但改成值班中
                    ADOConnection.runTask(mark, classesShiftService, "updateBatchState", Boolean.class, stateShiftIds, 1);
                    break;
                }
            } else {
                shiftRecord.setNextShiftId(shiftList0.get(i + 1).getId());
                shiftRecord.setStatus(1);
            }
            classesShiftRecords.add(shiftRecord);
            // 生成值班记录
            if (!CollectionUtils.isEmpty(classesShiftDTO.getStaffs())) {
                for (ClassesStaff staff : classesShiftDTO.getStaffs()) {
                    ClassesDutyRecord classesDutyRecord = new ClassesDutyRecord();
                    classesDutyRecord.build(staff.getStaffBy(),
                            staff.getStaffName(),
                            scheduleDTO.getDeptId(),
                            scheduleDTO.getDeptName(),
                            scheduleDTO.getLocationId(),
                            scheduleDTO.getLocationName(),
                            classesShiftDTO.getId(),
                            classesShiftDTO.getName(),
                            staff.getType(),
                            currentDate,
                            currentDate,
                            currentDate
                    );
                    classesDutyRecord.setWorkDuration(classesShiftDTO.getEndTime().getTime() - classesShiftDTO.getStartTime().getTime());
                    dutyRecords.add(classesDutyRecord);
                }
            }
            logShift(classesShiftDTO.getStartTime(), classesShiftDTO.getEndTime(), classesShiftDTO.getName(), "强制交接班");
        }
        // 更新所有班次状态
        if (!CollectionUtils.isEmpty(stateShiftIds)) {
            ADOConnection.runTask(mark, classesShiftService, "updateBatchState", Boolean.class, stateShiftIds, 2);
        }
        // 新增以往班次的交接班记录
        if (!CollectionUtils.isEmpty(classesShiftRecords)) {
            ADOConnection.runTask(mark, classesShiftRecordService, "saveBatch", Boolean.class, classesShiftRecords);
            // 新增班次的交接班事项
            List<ClassesTip> tipAll = new ArrayList<>();
            if (!CollectionUtils.isEmpty(tips)) {
                for (ClassesShiftRecord classesShiftRecord : classesShiftRecords) {
                    List<ClassesTip> collect = tips.stream().map(e -> {
                        ClassesTip tip = BeanUtil.toBean(e, ClassesTip.class);
                        tip.setRecordId(classesShiftRecord.getId());
                        return tip;
                    }).collect(Collectors.toList());
                    tipAll.addAll(collect);
                }
                ADOConnection.runTask(mark, classesTipService, "saveBatch", Boolean.class, tipAll);
            }
        }

        // 新增以往班次的值班记录
        if (!CollectionUtils.isEmpty(dutyRecords)) {
            ADOConnection.runTask(mark, classesDutyRecordService, "saveBatch", Boolean.class, dutyRecords);
        }

        // 存在 值班开始时间 < 当前时间 < 值班结束时间 的班次，则
        int currentShiftIndex = shiftList0.size();
        if (currentShiftIndex < shiftList.size() && shiftList.get(currentShiftIndex).getStartTime().before(currentDate)) {
            ClassesShiftDTO classesShiftDTO = shiftList.get(currentShiftIndex);
            logShift(classesShiftDTO.getStartTime(), classesShiftDTO.getEndTime(), classesShiftDTO.getName(), "当前班次");
            // 如果是首班
            if (currentShiftIndex == 0) {
                // 查询当前交接班记录
                ShiftRecordDTO currShiftRecordDTO = getCurrShiftRecordDTO(scheduleDTO.getId(), getCurrDs());
                // 如果本值为空，直接接班
                if (currShiftRecordDTO.getThisShift() == null || currShiftRecordDTO.getThisShiftId() == null) {
                    ADOConnection.runTask(mark, shiftService, "straightTakeover", Boolean.class, null, classesShiftDTO.getId());
                }
                // 如果本值不为空
                else {
                    ClassesShiftDTO thisShift = currShiftRecordDTO.getThisShift();
                    ClassesShiftDTO nextShift = currShiftRecordDTO.getNextShift();
                    // 如果 不是当前排班方案且下值未接班
                    if (!Objects.equals(currShiftRecordDTO.getScheduleId(), scheduleDTO.getId()) && nextShift != null && nextShift.getStatus() == 0) {
                        // 如果本值 值班中
                        if (thisShift.getStatus() == 1){
                            // 本值交班
                            ADOConnection.runTask(mark, shiftService, "handover", Boolean.class, currShiftRecordDTO);
                            logShift(thisShift.getStartTime(), thisShift.getEndTime(), thisShift.getName(), "执行交班");
                        }
                        if (thisShift.getStatus() != 0){
                            // 下值接班
                            ADOConnection.runTask(mark, shiftService, "takeover", Boolean.class, currShiftRecordDTO.getId());
                            logShift(nextShift.getStartTime(), nextShift.getEndTime(), nextShift.getName(), "执行接班");
                        }
                    }
                }
                return classesShiftDTO;
            }

            // 接班
            ShiftQuery shiftQuery = new ShiftQuery();
            shiftQuery.setThisShiftId(shiftList.get(currentShiftIndex - 1).getId());
            ShiftRecordDTO shiftRecordDTO = ADOConnection.runTask(mark, shiftService, "detail", ShiftRecordDTO.class, shiftQuery);
            shiftRecordDTO.setNextShiftId(classesShiftDTO.getId());
            shiftRecordDTO.setNextShift(classesShiftDTO);
            shiftRecordDTO.setNextTime(currentDate);
            ADOConnection.runTask(mark, shiftService, "takeover", Boolean.class, shiftRecordDTO.getId());
            return classesShiftDTO;
        }
        // 全是未来班次则以上都不执行，直接返回null
        return null;
    }

    /**
     * 执行交班任务
     */
    @XxlJob(value = "executeHandoverTask")
    public void executeHandoverTask() {
        CronTask cronTask = xxlJobService.getCronTaskByXxlJobId((int) XxlJobHelper.getJobId());
        String businessId = cronTask.getBusinessId();
        String mark = cronTask.getMark();
        if (mark != null) {
            setCurrDs(mark);
        }
        ShiftRecordDTO shiftRecordDTO = getCurrShiftRecordDTO(businessId, mark);
        // 执行交班
        ADOConnection.runTask(mark, shiftService, "handover", Boolean.class, shiftRecordDTO);
        ClassesShiftDTO thisShift = shiftRecordDTO.getThisShift();
        logShift(thisShift.getStartTime(), thisShift.getEndTime(), thisShift.getName(), "执行交班");
        // 执行线程任务需要拿到代理对象
        ShiftTask shiftTask = SpringUtil.getBean(ShiftTask.class);
        // 如果班次已经结束，老版本处理：移除定时任务；当前处理：停用排班方案
        if (shiftRecordDTO.getNextShift() == null) {
            ADOConnection.runTask(getCurrDs(), classesScheduleService, "updateStatus", Boolean.class, businessId, 1);
            shiftTask.deleteTask(businessId);
            return;
        }
        // 如果本值值班结束时间 == 下值值班开始时间
        if (thisShift.getEndTime().equals(shiftRecordDTO.getNextShift().getStartTime())) {
            // 直接执行接班任务
            executeTakeoverTask(shiftRecordDTO);
        } else {
            // 创建接班任务
            shiftTask.createTakeoverTask(businessId, shiftRecordDTO.getNextShift().getStartTime(), "admin", shiftRecordDTO.getScheduleName(), mark);
        }
    }

    /**
     * 执行接班任务
     */
    @XxlJob(value = "executeTakeoverTask")
    public void executeTakeoverTask(ShiftRecordDTO shiftRecordDTO) {
        CronTask cronTask = xxlJobService.getCronTaskByXxlJobId((int) XxlJobHelper.getJobId());
        String businessId = cronTask.getBusinessId();
        String mark = cronTask.getMark();
        if (mark != null) {
            setCurrDs(mark);
        }
        if (shiftRecordDTO == null) {
            shiftRecordDTO = getCurrShiftRecordDTO(businessId, mark);
        } else {
            businessId = shiftRecordDTO.getScheduleId();
            mark = mark == null ? getCurrDs() : mark;
        }
        ClassesShiftDTO nextShift = shiftRecordDTO.getNextShift();
        // 执行接班
        if (StringUtils.isEmpty(shiftRecordDTO.getId())) {
            // 直接接班
            ADOConnection.runTask(mark, shiftService, "straightTakeover", Boolean.class, null, nextShift.getId());
            logShift(nextShift.getStartTime(), nextShift.getEndTime(), nextShift.getName(), "执行直接接班");
        } else {
            // 普通接班
            try {
                ADOConnection.runTask(mark, shiftService, "takeover", Boolean.class, shiftRecordDTO.getId());
            } catch (IllegalStateException e) {
                if ("班次状态有修改，请关闭页面，重新接班。原因：本值还未交班，可能是被驳回过".equals(e.getMessage())) {
                    // 等待20s，再次接班
                    try {
                        Thread.sleep(20000);
                    } catch (InterruptedException ex) {
                        log.error(ex.getMessage(),ex);
                    }
                    ADOConnection.runTask(mark, shiftService, "takeover", Boolean.class, shiftRecordDTO.getId());
                }
            }
            logShift(nextShift.getStartTime(), nextShift.getEndTime(), nextShift.getName(), "执行接班");
        }

        // 执行线程任务需要拿到代理对象
        ShiftTask shiftTask = SpringUtil.getBean(ShiftTask.class);
        // 创建交班任务
        shiftTask.createHandoverTask(businessId, shiftRecordDTO.getNextShift().getEndTime(), "admin", shiftRecordDTO.getScheduleName(), mark);

    }

    private ShiftRecordDTO getCurrShiftRecordDTO(String businessId, String mark) {
        ScheduleDTO scheduleDTO = ADOConnection.runTask(mark, classesScheduleService, "getDtoById", ScheduleDTO.class, businessId);
        // 查询交接班面板信息
        ShiftRecordQuery query = new ShiftRecordQuery();
        query.setDeptId(scheduleDTO.getDeptId());
        query.setLocationId(scheduleDTO.getLocationId());
        query.setStaffTypes(Collections.singletonList(scheduleDTO.getStaffType()));
        ChangeShiftDTO changeShiftDTO = ADOConnection.runTask(mark, shiftService, "getChangeShift", ChangeShiftDTO.class, query);
        // 获取交班记录
        ShiftQuery shiftQuery = new ShiftQuery();

        // 设置本值id
        Optional.ofNullable(changeShiftDTO)
                .map(ChangeShiftDTO::getThisClassesShift)
                .map(BaseBean::getId)
                .ifPresent(shiftQuery::setThisShiftId);

        // 设置下值id
        Optional.ofNullable(changeShiftDTO)
                .map(ChangeShiftDTO::getNextClassesShift)
                .map(BaseBean::getId)
                .ifPresent(shiftQuery::setNextShiftId);

        // 如果本值为空，构造一个有下值信息的交接班记录数据
        if (shiftQuery.getThisShiftId() == null) {
            ShiftRecordDTO shiftRecordDTO = new ShiftRecordDTO();
            shiftRecordDTO.setScheduleId(scheduleDTO.getId());
            shiftRecordDTO.setScheduleName(scheduleDTO.getName());
            ClassesShiftDTO nextShiftDto = ADOConnection.runTask(mark, classesShiftService, "getDtoById", ClassesShiftDTO.class, shiftQuery.getNextShiftId());
            shiftRecordDTO.setNextShift(nextShiftDto);
            return shiftRecordDTO;
        }

        return ADOConnection.runTask(mark, shiftService, "detail", ShiftRecordDTO.class, shiftQuery);
    }

    /**
     * 日志记录
     * exp:
     * 自动交班，班次：2022-01-06 00:00 至 2022-01-07 00:00 【全天】
     *
     * @param startTime 班次开始时间
     * @param endTime   班次结束时间
     * @param shiftName 班次名称
     * @param title     标题
     */
    private void logShift(Date startTime, Date endTime, String shiftName, String title) {
        log.info("{}，班次：{} 至 {} 【{}】", title, DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm"), DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm"), shiftName);
    }
}
